package com.inno.life.domain.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import com.github.pagehelper.Page;
import com.inno.life.common.constant.DefaultValueConstant;
import com.inno.life.common.constant.MessageTypeConstant;
import com.inno.life.common.entity.PageResult;
import com.inno.life.common.enums.IsDeletedFlagEnum;
import com.inno.life.common.enums.YesOrNoEnum;
import com.inno.life.common.utils.DateUtils;
import com.inno.life.domain.convert.MomentCommentConverter;
import com.inno.life.domain.dict.Constant;
import com.inno.life.domain.entity.MomentCommentBO;
import com.inno.life.domain.service.MomentCommentDomainService;
import com.inno.life.domain.websocket.ZeyPlannerSocket;
import com.inno.life.infra.basic.entity.PlannerMessages;
import com.inno.life.infra.basic.entity.PlannerMoment;
import com.inno.life.infra.basic.entity.PlannerMomentComment;
import com.inno.life.infra.basic.service.PlannerMessagesService;
import com.inno.life.infra.basic.service.PlannerMomentCommentService;
import com.inno.life.infra.basic.service.PlannerMomentService;
import com.inno.life.infra.entity.UserInfo;
import com.inno.life.infra.rpc.UserRpc;
import jakarta.websocket.Session;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author sean
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MomentCommentDomainDomainServiceImpl implements MomentCommentDomainService {
    private final PlannerMomentCommentService plannerMomentCommentService;
    private final PlannerMomentService plannerMomentService;
    private final ZeyPlannerSocket zeyPlannerSocket;
    private final ThreadPoolTaskExecutor lifeExecutor;
    private final UserRpc userRpc;
    private final PlannerMessagesService plannerMessagesService;


    /**
     * 评论
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(MomentCommentBO momentCommentBO) {
        PlannerMomentComment entity = MomentCommentConverter.INSTANCE.convertBOToEntity(momentCommentBO);
        entity.setId(IdUtil.getSnowflakeNextId());
        Long userId = momentCommentBO.getUserId();
        entity.setCreateBy(userId);
        Date nowDate = DateUtils.getNowDate();
        entity.setCreateTime(nowDate);
        entity.setUpdateBy(userId);
        entity.setUpdateTime(nowDate);
        entity.setReplyCount(DefaultValueConstant.MOMENT_DEFAULT_COUNT);
        entity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode().toString());
        Long parentId = entity.getParentId();
        if (parentId == null || parentId == 0){
            entity.setParentId(DefaultValueConstant.MOMENT_DEFAULT_COUNT.longValue());
        }else {
            PlannerMomentComment parentEntity = new PlannerMomentComment();
            parentEntity.setId(parentId);
            this.plannerMomentCommentService.updateReplyCount(parentEntity);
        }
        plannerMomentCommentService.insert(entity);
        Long momentId = entity.getMomentId();
        plannerMomentService.incrementCommentCount(momentId);

        CompletableFuture.runAsync(()->{
            PlannerMoment plannerMoment = plannerMomentService.queryById(momentId);
            Long toUserId = plannerMoment.getUserId();
            Session session = zeyPlannerSocket.getSession(toUserId);
            JSONObject message = new JSONObject();
            message.putOnce("title", "评论消息");
            message.putOnce("type", MessageTypeConstant.COMMENT_MOMENT);
            message.putOnce("message", "有人评论了你的动态,快去看看吧");
            message.putOnce("moment", plannerMoment.getId().toString());
            PlannerMessages plannerMessages = new PlannerMessages();
            plannerMessages.setUserId(toUserId);
            plannerMessages.setFromId(userId);
            plannerMessages.setId(IdUtil.getSnowflakeNextId());
            plannerMessages.setType(Constant.MessagesType.COMMENT);
            plannerMessages.setCreateTime(DateUtils.getNowDate());
            UserInfo userInfo = userRpc.getUserInfoById(userId);
            plannerMessages.setContent("用户:" + userInfo.getUsername() + "评论了你的发布的动态");
            plannerMessages.setIsRead(YesOrNoEnum.NO.getCode());
            plannerMessagesService.insert(plannerMessages);
            if (session != null && session.isOpen()) {
                this.zeyPlannerSocket.sendMessage(session, message.toString());
            } else {
                log.warn("用户{}的socket连接已断开或不存在，无法发送点赞消息", userId);
                zeyPlannerSocket.putOfflineMessage(userId, message.toString());
            }
        },lifeExecutor);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(MomentCommentBO momentCommentBO) {
        PlannerMomentComment entity = MomentCommentConverter.INSTANCE.convertBOToEntity(momentCommentBO);
        Long currentUserId = momentCommentBO.getCurrentUserId();
        Date nowDate = DateUtils.getNowDate();
        entity.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode().toString());
        entity.setDeletedTime(nowDate);
        entity.setUpdateBy(currentUserId);
        entity.setUpdateTime(nowDate);
        this.plannerMomentCommentService.update(entity);

        this.plannerMomentService.decrementCommentCount(entity.getId());
    }

    @Override
    public PageResult<MomentCommentBO> list(MomentCommentBO momentCommentBO) {
        PlannerMomentComment plannerMomentComment = MomentCommentConverter.INSTANCE.convertBOToEntity(momentCommentBO);
        plannerMomentComment.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode().toString());
        // 查询所有
        plannerMomentComment.setParentId(null);
        Page<PlannerMomentComment> entityPage = this.plannerMomentCommentService.queryPage(plannerMomentComment);
        List<PlannerMomentComment> entityList = entityPage.getResult();

        List<MomentCommentBO> commentBOList = buildCommentTree(entityList, userRpc);
        return PageResult.of(commentBOList, entityPage.getTotal());
    }

    /**
     * 构建评论树的方法，同时设置用户信息
     *
     * @param commentList 从数据库获取的平级评论列表（PlannerMomentComment实体列表）
     * @param userRpc 用户信息获取服务（假设可以通过它获取用户信息）
     * @return 构建好的以MomentCommentBO为节点的评论树的根节点列表
     */
    public static List<MomentCommentBO> buildCommentTree(List<PlannerMomentComment> commentList, UserRpc userRpc) {
        // 用于存储转换后的MomentCommentBO对象，以id为键，方便后续查找和构建树结构
        Map<Long, MomentCommentBO> commentMap = new HashMap<>();
        // 先将所有评论转换为MomentCommentBO并放入map中，同时获取用户信息并设置
        for (PlannerMomentComment comment : commentList) {
            MomentCommentBO commentBO = MomentCommentConverter.INSTANCE.convertEntityToBO(comment);
            commentMap.put(commentBO.getId(), commentBO);

            UserInfo userInfo = userRpc.getUserInfoById(commentBO.getUserId());
            commentBO.setUsername(userInfo.getUsername());
            commentBO.setAvatar(userInfo.getAvatar());
        }

        // 用于存储根节点的列表，即parentId为默认值或null的评论
        List<MomentCommentBO> rootComments = new ArrayList<>();

        // 遍历评论列表，构建树结构并为子评论设置用户信息（如果有）
        for (PlannerMomentComment comment : commentList) {
            MomentCommentBO commentBO = commentMap.get(comment.getId());
            Long parentId = comment.getParentId();
            if (parentId == null || parentId == 0) {
                rootComments.add(commentBO);
            } else {
                MomentCommentBO parentCommentBO = commentMap.get(parentId);
                if (parentCommentBO!= null) {
                    if (parentCommentBO.getChildren() == null) {
                        parentCommentBO.setChildren(new ArrayList<>());
                    }
                    parentCommentBO.getChildren().add(commentBO);

                    // 为子评论设置用户信息（因为已经在前面转换时设置过当前评论的用户信息，这里只处理子评论情况）
                    if (commentBO.getChildren() == null) {
                        commentBO.setChildren(new ArrayList<>());
                    }
                    List<MomentCommentBO> children = commentBO.getChildren();
                    for (MomentCommentBO child : children) {
                        UserInfo userInfo = userRpc.getUserInfoById(child.getUserId());
                        child.setUsername(userInfo.getUsername());
                        child.setAvatar(userInfo.getAvatar());
                    }
                }
            }
        }
        return rootComments;
    }
}
